﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.IO;
using MQTTnet;
using MQTTnet.Server;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using MQTTnet.Client.Receiving;
using MQTTnet.Client.Connecting;
namespace MQTT服务端
{
    public partial class Form1 : Form
    {
        Timer timer = new Timer();
        List<ClientItem> clients = new List<ClientItem>();
        public Form1()
        {
            InitializeComponent();
            timer.Interval = 500;
            timer.Tick += Timer_Tick;
            timer.Start();
            InitSetting();
        }
        private void Timer_Tick(object sender, EventArgs e)
        {
            toolStripStatusDateTime.Text = DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss");
        }
        void InitSetting()
        {
            //获取本机所有的IP4地址
            string[] ips = Dns.GetHostAddresses(Environment.MachineName).Where(item => !item.IsIPv6LinkLocal).Select(item => item.ToString()).ToArray();
            comboIp_List.DataSource = ips;
            txtPort.Text = "8000";
            txtUserName.Text = "sa";
            txtPwd.Text = "1";
        }
        IMqttServer mqttServer;
        private void btnStart_Click(object sender, EventArgs e)
        {
            if (btnStart.Text.Equals("开始"))
            {
                IMqttServerOptions options = new MqttServerOptionsBuilder()
               .WithConnectionBacklog(10)
               .WithDefaultEndpointBoundIPAddress(IPAddress.Parse(comboIp_List.Text.Trim()))
               .WithDefaultEndpointPort(Convert.ToInt32(txtPort.Text.Trim()))
               .WithDefaultCommunicationTimeout(TimeSpan.FromMilliseconds(5000))
               .WithConnectionValidator(context =>
               {
                   //验证
                   if (ck_UserPwd.Checked)
                   {
                       if (!context.Username.Equals(txtUserName.Text))
                       {
                           context.ReasonCode = MQTTnet.Protocol.MqttConnectReasonCode.BadUserNameOrPassword;
                          
                           
                       }
                       if (!context.Password.Equals(txtPwd.Text))
                       {
                           context.ReasonCode = MQTTnet.Protocol.MqttConnectReasonCode.BadUserNameOrPassword;
                         
                       }
                   }
                   else
                   {
                       context.ReasonCode = MQTTnet.Protocol.MqttConnectReasonCode.Success;
                   }
               }).Build();
                mqttServer = new MqttFactory().CreateMqttServer();
                mqttServer.ApplicationMessageReceivedHandler = new MqttApplicationMessageReceivedHandlerDelegate(ApplicationMessageReceived);
                //服务开始事件
                mqttServer.StartedHandler = new MqttServerStartedHandlerDelegate(MqttServer_StartedAsync);
                //服务停止事件
                mqttServer.StoppedHandler = new MqttServerStoppedHandlerDelegate(MqttServer_StoppedAsync);
                //客户端连接事件
                mqttServer.ClientConnectedHandler = new MqttServerClientConnectedHandlerDelegate(MqttServer_ClientConnectedAsync);
                //客户端断开连接事件
                mqttServer.ClientDisconnectedHandler = new MqttServerClientDisconnectedHandlerDelegate(MqttServer_ClientDisconnectedAsync);
                //客户端订阅事件
                mqttServer.ClientSubscribedTopicHandler = new MqttServerClientSubscribedTopicHandlerDelegate(MqttServer_ClientSubscribedTopicAsync);
                //客户端取消订阅事件
                mqttServer.ClientUnsubscribedTopicHandler = new MqttServerClientUnsubscribedTopicHandlerDelegate(MqttServer_ClientUnsubscribedTopicAsync);
               
                mqttServer.StartAsync(options);
           
                if (mqttServer.IsStarted)
                {
                    btnStart.Text = "断开";
                    btnStart.BackColor = Color.Green;
                    comboIp_List.Enabled = txtPort.Enabled = false;
                }
            }
            else
            {
                mqttServer.StopAsync().Wait();
                if (!mqttServer.IsStarted)
                {
                    btnStart.Text = "开始";
                    btnStart.BackColor = Color.Red;
                    comboIp_List.Enabled = txtPort.Enabled = true;
                }
                mqttServer.Dispose();
            }
        }
        private Task MqttServer_ClientUnsubscribedTopicAsync(MqttServerClientUnsubscribedTopicEventArgs arg)
        {
            //客户端取消订阅事件
            string msg = $"客户端ID：[{arg.ClientId}] 取消主题：[{arg.TopicFilter}] 订阅";
            AddLog(1, msg);
            //取消订阅
            ClientItem client = clients.FirstOrDefault(item => item.ClientID.Equals(arg.ClientId));
            client?.Topics.RemoveAll(item => item.Topic.Equals(arg.TopicFilter));
            return Task.FromResult(arg);
        }
        private Task MqttServer_ClientSubscribedTopicAsync(MqttServerClientSubscribedTopicEventArgs arg)
        {
            //客户端订阅事件
            string msg = $"客户端ID：[{arg.ClientId}]订阅主题：[{arg.TopicFilter.Topic}],Qos:[{arg.TopicFilter.QualityOfServiceLevel}]";
            AddLog(0, msg);
            TopicItem topic = new TopicItem { QualityOfServiceLevel = arg.TopicFilter.QualityOfServiceLevel, Topic = arg.TopicFilter.Topic };
            ClientItem client = clients.FirstOrDefault(item => item.ClientID.Equals(arg.ClientId));
            client?.Topics.Add(topic);
            return Task.FromResult(arg);
        }
        private Task MqttServer_ClientDisconnectedAsync(MqttServerClientDisconnectedEventArgs arg)
        {
            //客户端断开事件
            string msg = $"客户端ID：[{arg.ClientId}] 断开连接,EndPoint:{arg.Endpoint},断开连接类型：{arg.DisconnectType}";
            AddLog(1, msg);
            //移除该Client
            clients.RemoveAll(item => item.ClientID.Equals(arg.ClientId));
            //更新ListBox
            UpdateClientList();
            return Task.FromResult(arg);
        }
        private Task MqttServer_ClientConnectedAsync(MqttServerClientConnectedEventArgs arg)
        {
            //客户端连接事件
            string msg = $"客户端ID：[{arg.ClientId}]连接 ,EndPoint:{arg.Endpoint},UserName: {arg.UserName}";
            AddLog(0, msg);
            ClientItem client = new ClientItem
            {
                ClientID = arg.ClientId,
                EndPoint = arg.Endpoint

            };
            clients.Add(client);
            //更新ListBox
            UpdateClientList();
            return Task.FromResult(arg);
        }
        private Task ApplicationMessageReceived(MqttApplicationMessageReceivedEventArgs arg)
        {
            //客户端MessageReceived事件
            string msg = $"收到消息：发送者ID：[{arg.ClientId}] QoS：{arg.ApplicationMessage.QualityOfServiceLevel} topic:{arg.ApplicationMessage.Topic}, 内容：{arg.ApplicationMessage.ConvertPayloadToString()}";




            AddLog(1, msg);
            return Task.FromResult(arg);
        }
        private Task MqttServer_StoppedAsync(EventArgs arg)
        {
            //服务停止事件
            string msg = $"服务停止";
            AddLog(1, msg);
            clients.Clear();
            return Task.FromResult(arg);
        }
        private Task MqttServer_StartedAsync(EventArgs arg)
        {
            //服务开启事件
            string msg = $"服务开启";
            AddLog(0, msg);
            return Task.FromResult(arg);
        }
     
        private void ck_UserPwd_CheckedChanged(object sender, EventArgs e)
        {
            txtUserName.Enabled = txtPwd.Enabled = ck_UserPwd.Checked;
        }
        void AddLog(int cate, string msg)
        {
            if (lstview_Note.InvokeRequired)
            {
                this.Invoke(new Action(() =>
                {
                    ListViewItem item = new ListViewItem();
                    item.ImageIndex = cate;
                    item.SubItems.Add(DateTime.Now.ToString("HH:mm:ss"));
                    item.SubItems.Add(msg);
                    lstview_Note.Items.Add(item);
                    lstview_Note.EnsureVisible(lstview_Note.Items.Count - 1);
                    toolStripStatusConnectCount.Text = clients.Count.ToString();
                }));
            }
            else
            {
                ListViewItem item = new ListViewItem();
                item.ImageIndex = cate;
                item.SubItems.Add(DateTime.Now.ToString("HH:mm:ss"));
                item.SubItems.Add(msg);
                lstview_Note.Items.Add(item);
                lstview_Note.EnsureVisible(lstview_Note.Items.Count - 1);
                toolStripStatusConnectCount.Text = clients.Count.ToString();
            }
           
           
        }
        private void btnCreateClient_Click(object sender, EventArgs e)
        {
            ClientFrm frm = new ClientFrm();
            frm.Show();
        }

        private void lst_Client_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (lst_Client.SelectedItem != null)
            {
                ClientItem item = lst_Client.SelectedItem as ClientItem;
                lst_Topic.DataSource = item.Topics.Select(a => $"Topic:{a.Topic},QoS:{a.QualityOfServiceLevel}").ToArray();
            }
        }
        /// <summary>
        /// 更新clientList 列表
        /// </summary>
        void UpdateClientList()
        {
            this.Invoke(new Action(() => {
                lst_Client.Items.Clear();
                foreach (var item in clients)
                {
                    lst_Client.Items.Add(item);
                }
                toolStripStatusConnectCount.Text = clients.Count.ToString();
            }));
          
           
        }
    }
}
